﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LinkedList;

namespace UnitTestLinkedList
{
    [TestClass]
    public class UnitTestLinkedList
    {
        [TestMethod]
        public void TestLinkedListEmpty()
        {
            LinkedList<int> lli = new LinkedList<int>();
            Assert.AreEqual(true, lli.Empty);
        }

        [TestMethod]
        public void TestLinkedListAddFirst()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            Assert.AreEqual(false, lli.Empty);
        }

        [TestMethod]
        public void TestLinkedListFirst()
        {
            LinkedList<int> lli = new LinkedList<int>();
            try
            {
                int i = lli.First;
                Assert.Fail();
            }
            catch
            {
            }
            lli.AddFirst(5);
            Assert.AreEqual(5, lli.First);
            lli.AddFirst(6);
            Assert.AreEqual(6, lli.First);
        }

        [TestMethod]
        public void TestLinkedListAddLast()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddLast(5);
            Assert.AreEqual(false, lli.Empty);
        }

        [TestMethod]
        public void TestLinkedListLast()
        {
            LinkedList<int> lli = new LinkedList<int>();
            try
            {
                int i = lli.Last;
                Assert.Fail();
            }
            catch
            {
            }
            lli.AddFirst(5);
            Assert.AreEqual(5, lli.Last);
            lli.AddFirst(6);
            lli.AddLast(4);
            Assert.AreEqual(4, lli.Last);
        }

        [TestMethod]
        public void TestLinkedListClear()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            Assert.AreEqual(false, lli.Empty);
            lli.Clear();
            Assert.AreEqual(true, lli.Empty);
        }

        [TestMethod]
        public void TestLinkedListRemoveFirst()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            Assert.AreEqual(6, lli.First);
            lli.RemoveFirst();
            Assert.AreEqual(5, lli.First);
            lli.RemoveFirst();
            Assert.AreEqual(true, lli.Empty);
            try
            {
                int i = lli.First;
                Assert.Fail();
            }
            catch
            {
            } 
            try
            {
                int i = lli.Last;
                Assert.Fail();
            }
            catch
            {
            }
        }

        [TestMethod]
        public void TestLinkedListRemoveLast()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            Assert.AreEqual(5, lli.Last);
            lli.RemoveLast();
            Assert.AreEqual(6, lli.Last);
            lli.RemoveLast();
            Assert.AreEqual(true, lli.Empty);
            try
            {
                int i = lli.First;
                Assert.Fail();
            }
            catch
            {
            }
            try
            {
                int i = lli.Last;
                Assert.Fail();
            }
            catch
            {
            }
        }

        [TestMethod]
        public void TestLinkedListIteration()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            int i = 6;
            foreach (var item in lli)
            {
                Assert.AreEqual(i, item);
                i--;
            }
        }

        [TestMethod]
        public void TestLinkedListCount()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            Assert.AreEqual(4, lli.Count);
            lli.RemoveFirst();
            Assert.AreEqual(3, lli.Count);
            lli.RemoveLast();
            Assert.AreEqual(2, lli.Count); 
            lli.RemoveFirst();
            Assert.AreEqual(1, lli.Count);
            lli.RemoveLast();
            Assert.AreEqual(0, lli.Count);
            Assert.AreEqual(true, lli.Empty);
        }

        [TestMethod]
        public void TestLinkedListContains()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            Assert.AreEqual(true, lli.Contains(6));
            lli.RemoveFirst();
            Assert.AreEqual(false, lli.Contains(6));
        }

        [TestMethod]
        public void TestLinkedListFind()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            Assert.AreEqual(3, lli.Find(3));
            Assert.AreEqual(5, lli.Find(5));
            Assert.AreEqual(0, lli.Find(75));
        }

        [TestMethod]
        public void TestLinkedListRemove()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            Assert.AreEqual(6, lli.First);
            Assert.AreEqual(3, lli.Last);
            Assert.AreEqual(4, lli.Count);
            lli.Remove(6);
            Assert.AreEqual(5, lli.First);
            Assert.AreEqual(3, lli.Last);
            Assert.AreEqual(3, lli.Count);
            lli.Remove(4);
            Assert.AreEqual(5, lli.First);
            Assert.AreEqual(3, lli.Last);
            Assert.AreEqual(2, lli.Count);
            lli.Remove(3);
            Assert.AreEqual(5, lli.First);
            Assert.AreEqual(5, lli.Last);
            Assert.AreEqual(1, lli.Count);
            lli.Remove(5);
            try 
            {
                int i = lli.First;
                Assert.Fail();
            }
            catch
            {
            }
            try
            {
                int i = lli.Last;
                Assert.Fail();
            }
            catch
            {
            }
            Assert.AreEqual(0, lli.Count);
        }

        [TestMethod]
        public void TestLinkedListCopyTo()
        {
            LinkedList<int> lli = new LinkedList<int>();
            lli.AddFirst(5);
            lli.AddFirst(6);
            lli.AddLast(4);
            lli.AddLast(3);
            int[] ia1 = new int[4];
            lli.CopyTo(ia1, 0);
            int[] ia2 = new int[10];
            lli.CopyTo(ia2, 5);

            int[] ia1Expected = new int[4] { 6, 5, 4, 3 };
            int[] ia2Expected = new int[10] {0, 0, 0, 0, 0, 6, 5, 4, 3, 0};

            for (int i = 0; i < 4; i++)
            {
                Assert.AreEqual(ia1Expected[i], ia1[i]);
            }
            for (int i = 0; i < 10; i++)
            {
                Assert.AreEqual(ia2Expected[i], ia2[i]);
            }
        }
    }
}
